﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Lincolnwood.Foundation.Scheduling.Data.NHibernate;
using NHibernate;
using Lincolnwood.Foundation.Common.Data.NHibernate;
using Lincolnwood.Foundation.Common.Data;

namespace Lincolnwood.Foundation.Scheduling.Tests
{
    [TestClass]
    public class NHibernateScheduleRepositoryTests
    {
        private NHibernateHelper _nHibernateHelper = new NHibernateHelper();
        private IUnitOfWork _unitOfWork;

        public NHibernateScheduleRepositoryTests()
        {
            _nHibernateHelper.ConfigureWith(typeof(NHibernateEventsRepository).Assembly);
        }

        [TestInitialize]
        public void TestInitialize()
        {
            _nHibernateHelper.GenerateSchema();
            _unitOfWork = new NHibernateSchedulingUnitOfWork();
        }

        [TestMethod]
        public void Can_Generate_Schema()
        {
            _nHibernateHelper.GenerateSchema();
        }

        [TestMethod]
        public void Can_GetEventDefinitionsInRange_UsingEmptyDB_GetsNothing()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var results = repository.GetEventDefinitionsInRange(DateTime.Parse("August 20, 2012"), DateTime.Parse("August 25, 2012"));

        }

        [TestMethod]
        public void Can_SaveNonRecurringEventDefinition_WithoutErrors()
        {
            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            repository.Add(target);

            _unitOfWork.Flush();
        }

        [TestMethod]
        public void Can_SaveDailyRecurringEventDefinition_WithoutErrors()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            target.SetDailyRecurrence(DateTime.Parse("May 12, 2012"), 1);
            repository.Add(target);

            _unitOfWork.Flush();
        }

        [TestMethod]
        public void Can_SaveAndRetrieveDailyRecurringEventDefinition_WithoutErrors()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            target.SetDailyRecurrence(DateTime.Parse("May 12, 2012"), 1);
            repository.Add(target);
            _unitOfWork.Flush();

            var retrievedTarget = repository.GetEventDefinitionsInRange(DateTime.Parse("May 7, 2012"), DateTime.Parse("May 9, 2012")).FirstOrDefault<RecurrableEventDefinition>();

            Assert.IsNotNull(retrievedTarget);
            Assert.IsNotNull(retrievedTarget.Recurrence);

        }

        [TestMethod]
        [ExpectedException(typeof(NHibernate.Exceptions.GenericADOException))]
        public void Cannot_SaveDailyRecurringEventDefinition_UsingSharedRecurrencePattern()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target1 = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            var target2 = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 12, 2012 1:00 PM"), DateTime.Parse("May 12, 2012 3:00 PM"));
            
            DailyRecurrencePattern sharedPattern = new DailyRecurrencePattern(DateTime.Parse("May 24, 2012 1:00 PM"), 1);
            
            target1.Recurrence = sharedPattern;
            target2.Recurrence = sharedPattern;

            repository.Add(target1);
            repository.Add(target2);

            _unitOfWork.Flush();
        }

        [TestMethod]
        public void Can_Save2DailyRecurringEventDefinitions_WithNoRecurrencePattern()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target1 = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            var target2 = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 12, 2012 1:00 PM"), DateTime.Parse("May 12, 2012 3:00 PM"));

            repository.Add(target1);
            repository.Add(target2);

            _unitOfWork.Flush();
        }
        [TestMethod]
        public void Can_Save_Remove_And_Retrieve_DailyRecurringEventDefinition_GetsNothing()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            target.SetDailyRecurrence(DateTime.Parse("May 12, 2012"), 1);
            repository.Add(target);
            _unitOfWork.Flush();


            repository.RemoveById(target.Id);
            _unitOfWork.Flush();


            var retrievedTarget = repository.GetEventDefinitionsInRange(DateTime.Parse("May 7, 2012"), DateTime.Parse("May 9, 2012")).FirstOrDefault<RecurrableEventDefinition>();

            Assert.IsNull(retrievedTarget);
        }

        [TestMethod]
        public void Can_SaveAndRetrieveDailyRecurringEventDefinitionIncludingDeviations_WithoutErrors()
        {

            var repository = new NHibernateEventsRepository(_unitOfWork);
            var target = new RecurrableEventDefinition(Guid.NewGuid(), "Test Event", "This is a sample event for unit testing.", DateTime.Parse("May 8, 2012 1:00 PM"), DateTime.Parse("May 8, 2012 3:00 PM"));
            target.SetDailyRecurrence(DateTime.Parse("May 12, 2012"), 1);
            target.Recurrence.RemoveInstance(DateTime.Parse("May 10, 2012 1:00 PM"));
            repository.Add(target);
            _unitOfWork.Flush();


            var retrievedTarget = repository.GetEventDefinitionsInRange(DateTime.Parse("May 7, 2012"), DateTime.Parse("May 9, 2012")).FirstOrDefault<RecurrableEventDefinition>();

            Assert.IsNotNull(retrievedTarget);
            Assert.IsNotNull(retrievedTarget.Recurrence);

        }
    }
}
